package com.huarun.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;

/**
 * 对httpclient操作的工具类 需配置maven配置 <!--导入HttpClient依赖jar --> <dependency>
 * <groupId>org.apache.httpcomponents</groupId>
 * <artifactId>httpclient</artifactId> <version>4.5.3</version> </dependency>
 * <dependency> <groupId>org.apache.httpcomponents</groupId>
 * <artifactId>httpclient-cache</artifactId> <version>4.5.3</version>
 * </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId>
 * <artifactId>httpmime</artifactId> <version>4.5.3</version> </dependency>
 * 
 * */
@SuppressWarnings("unused")
public class HttpRequestUtils {
	// utf-8字符编码
	private static final String CHARSET_UTF_8 = "utf-8";
	// HTTP内容类型。
	private static final String CONTENT_TYPE_TEXT_HTML = "text/xml";
	// HTTP内容类型。相当于form表单的形式，提交数据
	private static final String CONTENT_TYPE_FORM_URL = "application/x-www-form-urlencoded";
	// HTTP内容类型。相当于form表单的形式，提交数据
	private static final String CONTENT_TYPE_JSON_URL = "application/json;charset=utf-8";
	// 连接管理器
	private static PoolingHttpClientConnectionManager pool;
	// 请求配置
	private static RequestConfig requestConfig;

	// 日志记录
	private static Logger logger = Logger.getLogger(HttpRequestUtils.class.getName());

	/**
	 * 初始化HttpClientTest
	 * */
	static {
		try {
			// System.out.println("初始化HttpClientTest~~~开始");
			SSLContextBuilder builder = new SSLContextBuilder();
			builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
			SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build());
			// 配置同时支持 HTTP 和 HTPPS
			Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory> create()
					.register("http", PlainConnectionSocketFactory.getSocketFactory()).register("https", sslsf).build();
			// 初始化连接管理器
			pool = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
			// 将最大连接数增加到200，实际项目最好从配置文件中读取这个值
			pool.setMaxTotal(200);
			// 设置最大路由
			pool.setDefaultMaxPerRoute(2);
			// 根据默认超时限制初始化requestConfig
			int socketTimeout = 10000;
			int connectTimeout = 10000;
			int connectionRequestTimeout = 10000;
			requestConfig = RequestConfig.custom().setConnectionRequestTimeout(connectionRequestTimeout)
					.setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();

			// System.out.println("初始化HttpClientTest~~~结束");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (KeyStoreException e) {
			e.printStackTrace();
		} catch (KeyManagementException e) {
			e.printStackTrace();
		}

		// 设置请求超时时间
		requestConfig = RequestConfig.custom().setSocketTimeout(50000).setConnectTimeout(50000)
				.setConnectionRequestTimeout(50000).build();
	}

	/**
	 * 获取HttpClient连接
	 * */
	public static CloseableHttpClient getHttpClient() {
		CloseableHttpClient httpClient = HttpClients.custom()
				// 设置连接池管理
				.setConnectionManager(pool)
				// 设置请求配置
				.setDefaultRequestConfig(requestConfig)
				// 设置重试次数
				.setRetryHandler(new DefaultHttpRequestRetryHandler(0, false)).build();
		return httpClient;
	}

	/**
	 * 关闭httpClient连接
	 * */
	public static boolean closeHttpClient(CloseableHttpClient httpClient) {
		try {
			httpClient.close();
			return true;
		} catch (IOException e) {
			e.printStackTrace();
			return false;
		}
	}

	/**
	 * post请求
	 * 
	 * @param url
	 *            url地址
	 * @param jsonParam
	 *            参数
	 * @param noNeedResponse
	 *            不需要返回结果true,不返回，false返回
	 */
	public static JSONObject httpPost(String url, JSONObject jsonParam, boolean noNeedResponse) {
		// post请求返回结果
		CloseableHttpClient httpClient = getHttpClient();
		JSONObject jsonResult = null;
		HttpPost method = new HttpPost(url);
		try {
			if (null != jsonParam) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				method.setEntity(entity);
			}
			HttpResponse result = httpClient.execute(method);
			url = URLDecoder.decode(url, "UTF-8");
			/** 请求发送成功，并得到响应 **/
			if (result.getStatusLine().getStatusCode() == 200) {
				String str = "";
				try {
					/** 读取服务器返回过来的json字符串数据 **/
					str = EntityUtils.toString(result.getEntity());
					if (noNeedResponse) {
						return null;
					}
					/** 把json字符串转换成json对象 **/
					jsonResult = JSONObject.parseObject(str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			} else {
				method.abort();
				return null;
			}
		} catch (IOException e) {
			if (method != null) {
				method.abort();
			}
			logger.error("post请求提交失败:" + url, e);
		}
		return jsonResult;
	}

	/**
	 *
	 * @param url url地址
	 * @param jsonParam 参数
	 * @return 返回值
	 */
	public static JSONObject httpPost(String url, JSONObject jsonParam) {
		return httpPost(url, jsonParam, false);
	}

	/**
	 * 发送get请求
	 * 
	 * @param url
	 *            路径
	 * @return
	 */
	public static JSONObject httpGet(String url) {
		// get请求返回结果
		JSONObject jsonResult = null;
		// 发送get请求
		HttpGet request = null;
		try {
			CloseableHttpClient httpClient = getHttpClient();
			request = new HttpGet(url);
			HttpResponse response = httpClient.execute(request);

			/** 请求发送成功，并得到响应 **/
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				/** 读取服务器返回过来的json字符串数据 **/
				String strResult = EntityUtils.toString(response.getEntity());
				/** 把json字符串转换成json对象 **/
				jsonResult = JSONObject.parseObject(strResult);
				url = URLDecoder.decode(url, "UTF-8");
			} else {
				request.abort();
				logger.error("get请求提交失败:" + url);
				return null;
			}
		} catch (IOException e) {
			if (request != null) {
				request.abort();
			}
			logger.error("get请求提交失败:" + url, e);
			return null;
		}
		return jsonResult;
	}

	/**
	 * 向指定 URL 发送POST方法的请求 （调用pinyinwang专用接口）
	 * @param url
	 *            发送请求的 URL
	 * @param param
	 *            请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
	 * @return 所代表远程资源的响应结果
	 */
	public static String sendPost(String url, String param) {
		PrintWriter out = null;
		BufferedReader in = null;
		String result = "";
		try {
			URL realUrl = new URL(url);
			// 打开和URL之间的连接
			URLConnection conn = realUrl.openConnection();
			// 设置通用的请求属性
			conn.setRequestProperty("accept", "*/*");
			conn.setRequestProperty("connection", "Keep-Alive");
			conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
			// 发送POST请求必须设置如下两行
			conn.setDoOutput(true);
			conn.setDoInput(true);
			// 获取URLConnection对象对应的输出流
			out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
			// 发送请求参数
			out.print(param);
			// flush输出流的缓冲
			out.flush();
			// 定义BufferedReader输入流来读取URL的响应
			in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "utf-8"));
			String line;
			while ((line = in.readLine()) != null) {
				result += line;
			}
		} catch (Exception e) {
			System.out.println("发送 POST 请求出现异常！" + e);
			logger.error("发送 POST 请求出现异常！" + e.getMessage(), e);
		} finally {
			//使用finally块来关闭输出流、输入流
			try {
				if (out != null) {
					out.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (IOException ex) {
				logger.error("发送 POST 请求关闭流错误！" + ex.getMessage(), ex);
			}
		}
		return result;
	}

	/**
	 *
	 * @param url url地址
	 * @param jsonParam 参数
	 * @return 返回值
	 */
	public static String httpPostReturnStr(String url, JSONObject jsonParam) {
		// post请求返回结果
		CloseableHttpClient httpClient = getHttpClient();
		HttpPost method = new HttpPost(url);
		String str = null;
		try {
			if (null != jsonParam) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				method.setEntity(entity);
			}
			HttpResponse result = httpClient.execute(method);
			url = URLDecoder.decode(url, "UTF-8");
			/** 请求发送成功，并得到响应 **/
			if (result.getStatusLine().getStatusCode() == 200) {
				try {
					/** 读取服务器返回过来的json字符串数据 **/
					str = EntityUtils.toString(result.getEntity());
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			} else {
				method.abort();
				return null;
			}
		} catch (IOException e) {
			if (method != null) {
				method.abort();
			}
			logger.error("post请求提交失败:" + url, e);
		}
		return str;
	}

	public static String httpPostHistory(String url, JSONObject jsonParam, boolean noNeedResponse) {
		//post请求返回结果
		CloseableHttpClient httpClient = getHttpClient();
		String jsonResult = null;
		HttpPost method = new HttpPost(url);
		try {
			if (null != jsonParam) {
				//解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				method.setEntity(entity);

			}
			HttpResponse result = httpClient.execute(method);
			url = URLDecoder.decode(url, "UTF-8");
			/**请求发送成功，并得到响应**/
			System.out.println("MYCODE:" + result.getStatusLine().getStatusCode());
			if (result.getStatusLine().getStatusCode() == 200) {
				String str = "";
				try {
					/**读取服务器返回过来的json字符串数据**/
					str = EntityUtils.toString(result.getEntity());
					if (noNeedResponse) {
						return null;
					}
					/**把json字符串转换成json对象**/

					jsonResult = str;
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			} else {
				method.abort();
			}
		} catch (IOException e) {
			if (method != null) {
				method.abort();
			}
			logger.error("post请求提交失败:" + url, e);
		}
		return jsonResult;
	}

	//获取关注微信公众号的请求方法
	public static JSONArray httpPostGetArray(String url, JSONObject jsonParam, boolean noNeedResponse) {
		//post请求返回结果
		CloseableHttpClient httpClient = HttpClients.createDefault();
		JSONArray jsonResult = null;
		HttpPost method = new HttpPost(url);
		try {
			if (null != jsonParam) {
				//解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				method.setEntity(entity);
			}
			HttpResponse result = httpClient.execute(method);
			url = URLDecoder.decode(url, "UTF-8");
			/**请求发送成功，并得到响应**/
			if (result.getStatusLine().getStatusCode() == 200) {
				String str = "";
				try {
					/**读取服务器返回过来的json字符串数据**/
					str = EntityUtils.toString(result.getEntity());
					if (noNeedResponse) {
						return null;
					}
					/**把json字符串转换成json对象**/

					jsonResult = JSONArray.parseArray(str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			} else {
				method.abort();
			}
		} catch (IOException e) {
			if (method != null) {
				method.abort();
			}
			logger.error("post请求提交失败:" + url, e);
		}
		return jsonResult;
	}

	public static String sendHttpRequest(boolean b, Object object, String url, String getMethod) {
		// TODO Auto-generated method stub
		return null;
	}

	public static JSONObject httpPost(String url, String param) {
		CloseableHttpClient httpClient = getHttpClient();
		JSONObject jsonResult = null;
		HttpPost method = new HttpPost(url);
		try {
			System.out.println("==============url:" + url);
			System.out.println("==============param:" + param);
			if (null != param) {
				StringEntity entity = new StringEntity(param, "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				method.setEntity(entity);
			}
			HttpResponse result = httpClient.execute(method);
			System.out.println("==============res:" + result.getStatusLine().getStatusCode());
			url = URLDecoder.decode(url, "UTF-8");

			if (result.getStatusLine().getStatusCode() == 200) {
				String str = "";
				try {
					str = EntityUtils.toString(result.getEntity());

					jsonResult = JSONObject.parseObject(str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			} else {
				method.abort();
				return null;
			}
		} catch (Exception e) {
			e.printStackTrace();
			if (method != null) {
				method.abort();
			}
			logger.error("post请求提交失败:" + url, e);
		}
		return jsonResult;
	}

	public static String http(String url, Map<String, Object> params) {
		URL u = null;
		HttpURLConnection con = null;

		StringBuffer sb = new StringBuffer();
		if (params != null) {
			for (Map.Entry e : params.entrySet()) {
				sb.append((String) e.getKey());
				sb.append("=");
				sb.append(e.getValue());
				sb.append("&");
			}
			sb.substring(0, sb.length() - 1);
		}
		System.out.println("send_url:" + url);
		System.out.println("send_data:" + sb.toString());
		try {
			u = new URL(url);
			con = (HttpURLConnection) u.openConnection();

			con.setRequestMethod("POST");
			con.setDoOutput(true);
			con.setDoInput(true);
			con.setUseCaches(false);
			con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
			OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), StandardCharsets.UTF_8);
			osw.write(sb.toString());
			osw.flush();
			osw.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (con != null) {
				con.disconnect();
			}

		}

		StringBuffer buffer = new StringBuffer();
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			String temp;
			while ((temp = br.readLine()) != null) {
				buffer.append(temp);
				buffer.append("\n");
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return buffer.toString();
	}

}
